package kin.json;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.lang.reflect.MethodUtils;

import kin.bean.system.MyEnumType;
import kin.system.util.ApplicationContextHelper;
import kin.system.util.StringUtil;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.deser.BeanDeserializer;
import com.fasterxml.jackson.databind.deser.BeanDeserializerBase;
import com.fasterxml.jackson.databind.deser.BeanDeserializerBuilder;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
import com.fasterxml.jackson.databind.deser.impl.BeanPropertyMap;
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.util.NameTransformer;

public class CustomerDeserializer extends JsonDeserializer<Object> implements ContextualDeserializer{
/*
	protected CustomerDeserializer(BeanDeserializerBase src,
			NameTransformer unwrapper) {
		super(src, unwrapper);
		// TODO Auto-generated constructor stub
	}
*/
	
 private Class targetClass; 
	
private Class gClass;
	

/*	public CustomerDeserializer(Class cls) {
		targetClass=cls;
}*/




	@Override
	public Object deserialize(JsonParser jp, DeserializationContext ctxt)throws IOException, JsonProcessingException {
		ObjectMapper om=new ObjectMapper();
	Object obj = null;
	Object bean;
		JsonNode jns=om.readTree(jp);
		Iterator<JsonNode> eles=jns.elements();
		JsonToken curr = jp.getCurrentToken();
		System.out.println("gClass:"+gClass);
		if(targetClass.getInterfaces()[0]==Collection.class){
			Collection c = null;
		
			
			if(!gClass.isPrimitive()&&curr!=JsonToken.VALUE_NULL){
				System.out.println("text1:"+jns.textValue());
				if(targetClass==List.class){
				c=new ArrayList();
				}
				if(targetClass==Set.class){
					
					c=new HashSet();
				
				}
				//om.re
				//om.re
				
				obj=om.readValue(jns.textValue(), om.getTypeFactory().constructCollectionType(targetClass, gClass));
				
				//obj=c;
		}
			
		}else{
			System.out.println("noooo");
			if(targetClass.isEnum()){
				System.out.println("eunm:"+jp.getIntValue());
				String cc=MyEnumType.format(jp.getIntValue());
				obj=MyEnumType.valueOf(cc);
				
			}else{
			bean=ApplicationContextHelper.getBean(StringUtil.fristLetterLowerCase(targetClass.getSimpleName())+"ServiceManagerIMP");
			try {
				obj=MethodUtils.invokeMethod(bean,"load", jp.getIntValue());
			} catch (NoSuchMethodException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			}
			
		}
		
		
		/*if(curr!=JsonToken.VALUE_NULL)
		if(jns.isArray()){
			
			//System.out.println();
			if(!gClass.get(0).isPrimitive()){
				Collection c = null;
				if(gClass.get(0)==List.class){
				c=new ArrayList();
				}
				if(gClass.get(0)==Set.class){
					
					c=new HashSet();
				
				}
				bean=ApplicationContextHelper.getBean(StringUtil.fristLetterLowerCase(gClass.get(0).getSimpleName())+"ServiceManagerIMP");
				
		while(eles.hasNext()){
			
			JsonNode jn=eles.next();
			try {
				c.add(MethodUtils.invokeMethod(bean,"load", jn.asInt()));
			} catch (NoSuchMethodException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("bbe:"+jn.asText());
		}
		
		obj=c;
		}
		}else{
		  
			bean=ApplicationContextHelper.getBean(StringUtil.fristLetterLowerCase(targetClass.getSimpleName())+"ServiceManagerIMP");
			try {
				obj=MethodUtils.invokeMethod(bean,"load", jp.getIntValue());
			} catch (NoSuchMethodException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}*/
		
		
		
		//System.out.println("ccl:"+jp.getText());
		//System.out.println("eeeee:"+jp.getCurrentName());
		
	
/*if(targetClass==List.class){
	return new ArrayList();
}else{
	
	try {
		return targetClass.newInstance();
	} catch (InstantiationException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (IllegalAccessException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
}*/


	   /* if (curr == JsonToken.VALUE_STRING) {
	      if( targetClass == null ) return jp.getText();
	      ObjectCodec codec = jp.getCodec();
	      if( codec == null ) {
	        return new ObjectMapper().readValue(jp.getText(), targetClass);
	      }
	      else if( codec instanceof ObjectMapper ) {
	        return ((ObjectMapper)codec).readValue(jp.getText(), targetClass);
	      }
	      else if( codec instanceof ObjectReader ) {
	        return ((ObjectReader)codec).withType(targetClass).readValue(jp.getText());
	      }
	      else {
	        return new ObjectMapper().readValue(jp.getText(), targetClass);
	      }
	    }*/

		//System.out.println("zzzzzzzzzzzzz:"+targetClass);
		//ObjectCodec oc= jp.getCodec();  
		 //System.out.println("ccode:"+oc.getClass());
		// JsonNode root =  oc.readTree(jp);
	//System.out.println("boolean:"+root.isArray());
	 
		
		return obj;
	}

	

	public JsonDeserializer<Object> createContextual(DeserializationContext ctxt,
			BeanProperty property) throws JsonMappingException {
	System.out.println(property.getName());
		
	  JavaType type = property.getType();
	 String name= property.getName();
	    //JavaType ofType = type.containedType(1);
	   
	    //System.out.println("name:"+name);
	   if(type.hasGenericTypes()){
		   System.out.println("type.containedTypeCount():"+type.containedTypeCount());
		  //for(int i=1;i<type.containedTypeCount()+1;i++){
			gClass=type.containedType(0).getRawClass();   
		  // }
		   //System.out.println("classs:"+type.getRawClass());
	   }
	    targetClass = type.getRawClass();
	    
		return this;
		
	}

	
	
	

	/*public CustomerDeserializer(BeanDeserializerBuilder builder,
			BeanDescription beanDesc, BeanPropertyMap properties,
			Map<String, SettableBeanProperty> backRefs,
			HashSet<String> ignorableProps, boolean ignoreAllUnknown,
			boolean hasViews) {
		
		
		super(builder, beanDesc, properties, backRefs, ignorableProps,
				ignoreAllUnknown, hasViews);
		System.out.println("hhhhhhhhh");
	}
*/
	

	

	
   
	/*@Override
	public Object deserialize(JsonParser jp, DeserializationContext ctxt)
			throws IOException, JsonProcessingException {
		
		
		
		 String value = jp.getText();
	        if (value.equals("one")) {
	            return 1;
	        } else if (value.equals("two")) {
	            return 2;
	        } else if (value.equals("three")) {
	            return 3;
	        } else {
	            return 0;
	        }
		
	}*/
}
